રિએક્ટ ફાઈબરના પ્રાયોરિટી લેન મેનેજમેન્ટમાં નિપુણતા મેળવીને ફ્લુઇડ યુઝર ઇન્ટરફેસને અનલૉક કરો. કન્કરન્ટ રેન્ડરિંગ, શેડ્યૂલર અને startTransition જેવી નવી APIs માટેની વિસ્તૃત માર્ગદર્શિકા.
રિએક્ટ ફાઈબર પ્રાયોરિટી લેન મેનેજમેન્ટ: રેન્ડરિંગ કંટ્રોલમાં ઊંડાણપૂર્વકનો અભ્યાસ
વેબ ડેવલપમેન્ટની દુનિયામાં, યુઝર એક્સપિરિયન્સ સર્વોપરી છે. એક ક્ષણ માટે ફ્રીઝ થવું, અટકતું એનિમેશન, અથવા ધીમું ઇનપુટ ફીલ્ડ એક ખુશ યુઝર અને નિરાશ યુઝર વચ્ચેનો તફાવત બની શકે છે. વર્ષોથી, ડેવલપર્સ બ્રાઉઝરના સિંગલ-થ્રેડેડ સ્વભાવ સામે લડી રહ્યા છે જેથી ફ્લુઇડ, રિસ્પોન્સિવ એપ્લિકેશન્સ બનાવી શકાય. રિએક્ટ 16 માં ફાઈબર આર્કિટેક્ચરની રજૂઆત સાથે, અને રિએક્ટ 18 માં કન્કરન્ટ ફીચર્સ સાથે તેની સંપૂર્ણ અનુભૂતિ સાથે, આ રમતમાં મૂળભૂત રીતે ફેરફાર થયો છે. રિએક્ટ એક એવી લાઇબ્રેરીમાંથી વિકસિત થયું છે જે ફક્ત UI રેન્ડર કરે છે, તેમાંથી એક એવી લાઇબ્રેરી બની છે જે બુદ્ધિપૂર્વક UI અપડેટ્સને શેડ્યૂલ કરે છે.
આ ઊંડાણપૂર્વકનો અભ્યાસ આ ઉત્ક્રાંતિના કેન્દ્રમાં છે: રિએક્ટ ફાઈબરનું પ્રાયોરિટી લેન મેનેજમેન્ટ. અમે સ્પષ્ટ કરીશું કે રિએક્ટ કેવી રીતે નક્કી કરે છે કે અત્યારે શું રેન્ડર કરવું, શું રાહ જોઈ શકે છે, અને તે યુઝર ઇન્ટરફેસને ફ્રીઝ કર્યા વિના બહુવિધ સ્ટેટ અપડેટ્સને કેવી રીતે સંભાળે છે. આ માત્ર એક શૈક્ષણિક કવાયત નથી; આ મુખ્ય સિદ્ધાંતોને સમજવાથી તમને વૈશ્વિક પ્રેક્ષકો માટે વધુ ઝડપી, સ્માર્ટ અને વધુ સ્થિતિસ્થાપક એપ્લિકેશન્સ બનાવવાની શક્તિ મળે છે.
સ્ટેક રિકન્સાઈલરથી ફાઈબર સુધી: રિરાઈટ પાછળનું 'શા માટે'
ફાઈબરની નવીનતાની પ્રશંસા કરવા માટે, આપણે પહેલા તેના પુરોગામી, સ્ટેક રિકન્સાઈલરની મર્યાદાઓને સમજવી જોઈએ. રિએક્ટ 16 પહેલાં, રિકન્સિલિએશન પ્રક્રિયા - જે એલ્ગોરિધમ રિએક્ટ એક ટ્રીને બીજા સાથે સરખાવવા માટે વાપરે છે જેથી DOM માં શું બદલવું તે નક્કી કરી શકાય - તે સિન્ક્રોનસ અને રિકર્સિવ હતી. જ્યારે કોઈ કમ્પોનન્ટનું સ્ટેટ અપડેટ થતું, ત્યારે રિએક્ટ સમગ્ર કમ્પોનન્ટ ટ્રીમાં ફરતું, ફેરફારોની ગણતરી કરતું, અને તેમને DOM પર એક જ, અવિરત ક્રમમાં લાગુ કરતું.
નાની એપ્લિકેશન્સ માટે, આ બરાબર હતું. પરંતુ ઊંડા કમ્પોનન્ટ ટ્રીવાળા જટિલ UI માટે, આ પ્રક્રિયામાં ઘણો સમય લાગી શકતો હતો - કહો કે, 16 મિલિસેકન્ડથી વધુ. કારણ કે જાવાસ્ક્રિપ્ટ સિંગલ-થ્રેડેડ છે, લાંબા સમય સુધી ચાલતું રિકન્સિલિએશન ટાસ્ક મુખ્ય થ્રેડને બ્લોક કરી દેતું હતું. આનો અર્થ એ થયો કે બ્રાઉઝર અન્ય નિર્ણાયક કાર્યોને સંભાળી શકતું ન હતું, જેમ કે:
- યુઝર ઇનપુટનો પ્રતિસાદ આપવો (જેમ કે ટાઇપિંગ અથવા ક્લિક કરવું).
- એનિમેશન ચલાવવું (CSS અથવા જાવાસ્ક્રિપ્ટ-આધારિત).
- અન્ય સમય-સંવેદનશીલ લોજિક ચલાવવું.
પરિણામ એ ઘટના હતી જેને "જંક" તરીકે ઓળખવામાં આવે છે - એક અટકતો, બિનપ્રતિભાવશીલ યુઝર એક્સપિરિયન્સ. સ્ટેક રિકન્સાઈલર એક-ટ્રેક રેલવેની જેમ કામ કરતું હતું: એકવાર ટ્રેન (એક રેન્ડર અપડેટ) તેની મુસાફરી શરૂ કરે, તે પૂર્ણ થવી જ જોઈએ, અને બીજી કોઈ ટ્રેન ટ્રેકનો ઉપયોગ કરી શકતી નહોતી. આ બ્લોકિંગ સ્વભાવ રિએક્ટના કોર એલ્ગોરિધમને સંપૂર્ણપણે ફરીથી લખવા માટેનું મુખ્ય પ્રેરક હતું.
રિએક્ટ ફાઈબર પાછળનો મુખ્ય વિચાર રિકન્સિલિએશનને એવું કંઈક તરીકે ફરીથી કલ્પના કરવાનો હતો જેને કામના નાના ટુકડાઓમાં વિભાજિત કરી શકાય. એક જ, મોનોલિથિક ટાસ્કને બદલે, રેન્ડરિંગને રોકી શકાય, ફરી શરૂ કરી શકાય અને રદ પણ કરી શકાય. સિન્ક્રોનસથી એસિન્ક્રોનસ, શેડ્યૂલ કરી શકાય તેવી પ્રક્રિયામાં આ ફેરફાર રિએક્ટને બ્રાઉઝરના મુખ્ય થ્રેડને નિયંત્રણ પાછું સોંપવાની મંજૂરી આપે છે, જે ખાતરી કરે છે કે યુઝર ઇનપુટ જેવા ઉચ્ચ-પ્રાથમિકતાવાળા કાર્યો ક્યારેય બ્લોક ન થાય. ફાઈબરે સિંગલ-ટ્રેક રેલવેને ઉચ્ચ-પ્રાથમિકતાવાળા ટ્રાફિક માટે એક્સપ્રેસ લેન સાથે મલ્ટિ-લેન હાઇવેમાં રૂપાંતરિત કર્યું.
'ફાઈબર' શું છે? કન્કરન્સીનો બિલ્ડિંગ બ્લોક
તેના મૂળમાં, "ફાઈબર" એ એક જાવાસ્ક્રિપ્ટ ઑબ્જેક્ટ છે જે કામના એકમનું પ્રતિનિધિત્વ કરે છે. તેમાં કમ્પોનન્ટ, તેના ઇનપુટ (props), અને તેના આઉટપુટ (children) વિશેની માહિતી હોય છે. તમે ફાઈબરને વર્ચ્યુઅલ સ્ટેક ફ્રેમ તરીકે વિચારી શકો છો. જૂના સ્ટેક રિકન્સાઈલરમાં, બ્રાઉઝરના કૉલ સ્ટેકનો ઉપયોગ રિકર્સિવ ટ્રી ટ્રાવર્સલને મેનેજ કરવા માટે થતો હતો. ફાઈબર સાથે, રિએક્ટ પોતાનો વર્ચ્યુઅલ સ્ટેક લાગુ કરે છે, જે ફાઈબર નોડ્સની લિંક્ડ લિસ્ટ દ્વારા રજૂ થાય છે. આ રિએક્ટને રેન્ડરિંગ પ્રક્રિયા પર સંપૂર્ણ નિયંત્રણ આપે છે.
તમારા કમ્પોનન્ટ ટ્રીમાં દરેક એલિમેન્ટ માટે એક સંબંધિત ફાઈબર નોડ હોય છે. આ નોડ્સ એકબીજા સાથે જોડાઈને ફાઈબર ટ્રી બનાવે છે, જે કમ્પોનન્ટ ટ્રી સ્ટ્રક્ચરને પ્રતિબિંબિત કરે છે. ફાઈબર નોડમાં નિર્ણાયક માહિતી હોય છે, જેમાં શામેલ છે:
- type and key: કમ્પોનન્ટ માટેના ઓળખકર્તાઓ, જેમ તમે રિએક્ટ એલિમેન્ટમાં જોશો.
- child: તેના પ્રથમ ચાઇલ્ડ ફાઈબર માટેનો પોઇન્ટર.
- sibling: તેના આગામી સિબલિંગ ફાઈબર માટેનો પોઇન્ટર.
- return: તેના પેરેન્ટ ફાઈબર માટેનો પોઇન્ટર (કામ પૂર્ણ કર્યા પછીનો 'રિટર્ન' પાથ).
- pendingProps and memoizedProps: પાછલા અને આગામી રેન્ડરના પ્રોપ્સ, જેનો ઉપયોગ ડિફિંગ માટે થાય છે.
- stateNode: વાસ્તવિક DOM નોડ, ક્લાસ ઇન્સ્ટન્સ અથવા અંતર્ગત પ્લેટફોર્મ એલિમેન્ટનો સંદર્ભ.
- effectTag: એક બિટમાસ્ક જે કરવાના કામનું વર્ણન કરે છે (દા.ત., Placement, Update, Deletion).
આ માળખું રિએક્ટને નેટિવ રિકર્ઝન પર આધાર રાખ્યા વિના ટ્રીને ટ્રાવર્સ કરવાની મંજૂરી આપે છે. તે એક ફાઈબર પર કામ શરૂ કરી શકે છે, રોકી શકે છે અને પછી તેનું સ્થાન ગુમાવ્યા વિના ફરી શરૂ કરી શકે છે. કામને રોકવાની અને ફરી શરૂ કરવાની આ ક્ષમતા એ મૂળભૂત મિકેનિઝમ છે જે રિએક્ટના તમામ કન્કરન્ટ ફીચર્સને સક્ષમ કરે છે.
સિસ્ટમનું હૃદય: શેડ્યૂલર અને પ્રાયોરિટી લેવલ્સ
જો ફાઈબર્સ કામના એકમો છે, તો શેડ્યૂલર એ મગજ છે જે નક્કી કરે છે કે કયું કામ ક્યારે કરવું. રિએક્ટ સ્ટેટમાં ફેરફાર થતાં જ તરત જ રેન્ડરિંગ શરૂ કરતું નથી. તેના બદલે, તે અપડેટને એક પ્રાયોરિટી લેવલ સોંપે છે અને શેડ્યૂલરને તેને હેન્ડલ કરવા કહે છે. શેડ્યૂલર પછી બ્રાઉઝર સાથે કામ કરે છે જેથી કામ કરવા માટે શ્રેષ્ઠ સમય શોધી શકાય, એ સુનિશ્ચિત કરીને કે તે વધુ મહત્વપૂર્ણ કાર્યોને અવરોધે નહીં.
શરૂઆતમાં, આ સિસ્ટમમાં અલગ-અલગ પ્રાયોરિટી લેવલ્સનો સમૂહ વપરાતો હતો. જ્યારે આધુનિક અમલીકરણ (લેન મોડેલ) વધુ સૂક્ષ્મ છે, ત્યારે આ વૈચારિક સ્તરોને સમજવું એ એક ઉત્તમ પ્રારંભિક બિંદુ છે:
- ImmediatePriority: આ સર્વોચ્ચ પ્રાથમિકતા છે, જે સિન્ક્રોનસ અપડેટ્સ માટે આરક્ષિત છે જે તરત જ થવા જોઈએ. તેનું ક્લાસિક ઉદાહરણ કંટ્રોલ્ડ ઇનપુટ છે. જ્યારે યુઝર ઇનપુટ ફીલ્ડમાં ટાઇપ કરે છે, ત્યારે UI એ ફેરફારને તરત જ પ્રતિબિંબિત કરવો જોઈએ. જો તેને થોડી મિલિસેકન્ડ માટે પણ મુલતવી રાખવામાં આવે, તો ઇનપુટ ધીમું લાગશે.
- UserBlockingPriority: આ એ અપડેટ્સ માટે છે જે યુઝરની અલગ-અલગ ક્રિયાપ્રતિક્રિયાઓથી પરિણમે છે, જેમ કે બટન પર ક્લિક કરવું અથવા સ્ક્રીનને ટેપ કરવું. આ યુઝરને તાત્કાલિક લાગવા જોઈએ પરંતુ જો જરૂરી હોય તો ખૂબ જ ટૂંકા ગાળા માટે મુલતવી રાખી શકાય છે. મોટાભાગના ઇવેન્ટ હેન્ડલર્સ આ પ્રાથમિકતા પર અપડેટ્સ ટ્રિગર કરે છે.
- NormalPriority: આ મોટાભાગના અપડેટ્સ માટે ડિફોલ્ટ પ્રાથમિકતા છે, જેમ કે ડેટા ફેચ (`useEffect`) અથવા નેવિગેશનથી ઉદ્ભવતા અપડેટ્સ. આ અપડેટ્સ તાત્કાલિક હોવા જરૂરી નથી, અને રિએક્ટ તેમને યુઝરની ક્રિયાપ્રતિક્રિયાઓમાં દખલ ન થાય તે રીતે શેડ્યૂલ કરી શકે છે.
- LowPriority: આ એવા અપડેટ્સ માટે છે જે સમય-સંવેદનશીલ નથી, જેમ કે ઑફસ્ક્રીન કન્ટેન્ટ રેન્ડર કરવું અથવા એનાલિટિક્સ ઇવેન્ટ્સ.
- IdlePriority: સૌથી ઓછી પ્રાથમિકતા, એવા કામ માટે કે જે ફક્ત ત્યારે જ થઈ શકે જ્યારે બ્રાઉઝર સંપૂર્ણપણે નિષ્ક્રિય હોય. આ એપ્લિકેશન કોડ દ્વારા ભાગ્યે જ સીધું વપરાય છે પરંતુ લોગિંગ અથવા ભવિષ્યના કામની પૂર્વ-ગણતરી જેવી બાબતો માટે આંતરિક રીતે વપરાય છે.
રિએક્ટ અપડેટના સંદર્ભના આધારે આપમેળે સાચી પ્રાથમિકતા સોંપે છે. ઉદાહરણ તરીકે, `click` ઇવેન્ટ હેન્ડલરની અંદરના અપડેટને `UserBlockingPriority` તરીકે શેડ્યૂલ કરવામાં આવે છે, જ્યારે `useEffect` ની અંદરના અપડેટને સામાન્ય રીતે `NormalPriority` તરીકે શેડ્યૂલ કરવામાં આવે છે. આ બુદ્ધિશાળી, સંદર્ભ-જાગૃત પ્રાથમિકતા એ છે જે રિએક્ટને આઉટ-ઓફ-ધ-બોક્સ ઝડપી અનુભવ કરાવે છે.
લેન થિયરી: આધુનિક પ્રાયોરિટી મોડેલ
જેમ જેમ રિએક્ટના કન્કરન્ટ ફીચર્સ વધુ અત્યાધુનિક બન્યા, તેમ તેમ સરળ આંકડાકીય પ્રાયોરિટી સિસ્ટમ અપૂરતી સાબિત થઈ. તે વિવિધ પ્રાથમિકતાઓના બહુવિધ અપડેટ્સ, વિક્ષેપો અને બેચિંગ જેવા જટિલ દૃશ્યોને સરળતાથી હેન્ડલ કરી શકતી ન હતી. આનાથી લેન મોડેલનો વિકાસ થયો.
એક જ પ્રાયોરિટી નંબરને બદલે, 31 "લેન" ના સમૂહ વિશે વિચારો. દરેક લેન એક અલગ પ્રાથમિકતાનું પ્રતિનિધિત્વ કરે છે. આ એક બિટમાસ્ક તરીકે લાગુ કરવામાં આવ્યું છે - એક 31-બિટ પૂર્ણાંક જ્યાં દરેક બિટ એક લેનને અનુરૂપ છે. આ બિટમાસ્ક અભિગમ અત્યંત કાર્યક્ષમ છે અને શક્તિશાળી કામગીરી માટે પરવાનગી આપે છે:
- બહુવિધ પ્રાથમિકતાઓનું પ્રતિનિધિત્વ: એક જ બિટમાસ્ક બાકી રહેલી પ્રાથમિકતાઓના સમૂહનું પ્રતિનિધિત્વ કરી શકે છે. ઉદાહરણ તરીકે, જો `UserBlocking` અપડેટ અને `Normal` અપડેટ બંને કમ્પોનન્ટ પર બાકી હોય, તો તેની `lanes` પ્રોપર્ટીમાં તે બંને પ્રાથમિકતાઓ માટેના બિટ્સ 1 પર સેટ હશે.
- ઓવરલેપ માટે તપાસ: બિટવાઇઝ ઓપરેશન્સ એ તપાસવાનું સરળ બનાવે છે કે લેનના બે સેટ ઓવરલેપ થાય છે કે કેમ અથવા એક સેટ બીજાનો સબસેટ છે કે કેમ. આનો ઉપયોગ એ નક્કી કરવા માટે થાય છે કે આવનારા અપડેટને હાલના કામ સાથે બેચ કરી શકાય છે કે કેમ.
- કામને પ્રાથમિકતા આપવી: રિએક્ટ બાકી રહેલા લેનના સમૂહમાં સૌથી વધુ-પ્રાથમિકતાવાળી લેનને ઝડપથી ઓળખી શકે છે અને ફક્ત તેના પર જ કામ કરવાનું પસંદ કરી શકે છે, હાલ માટે નીચલી-પ્રાથમિકતાવાળા કામને અવગણીને.
એક ઉપમા 31 લેનવાળા સ્વિમિંગ પૂલની હોઈ શકે છે. એક તાત્કાલિક અપડેટ, સ્પર્ધાત્મક તરવૈયાની જેમ, ઉચ્ચ-પ્રાથમિકતાવાળી લેન મેળવે છે અને કોઈપણ વિક્ષેપ વિના આગળ વધી શકે છે. કેટલાક બિન-તાકીદના અપડેટ્સ, સામાન્ય તરવૈયાઓની જેમ, નીચલી-પ્રાથમિકતાવાળી લેનમાં એકસાથે બેચ કરી શકાય છે. જો કોઈ સ્પર્ધાત્મક તરવૈયો અચાનક આવી પહોંચે, તો લાઇફગાર્ડ્સ (શેડ્યૂલર) પ્રાથમિકતાવાળા તરવૈયાને પસાર થવા દેવા માટે સામાન્ય તરવૈયાઓને રોકી શકે છે. લેન મોડેલ રિએક્ટને આ જટિલ સંકલનનું સંચાલન કરવા માટે અત્યંત દાણાદાર અને લવચીક સિસ્ટમ આપે છે.
ટુ-ફેઝ રિકન્સિલિએશન પ્રક્રિયા
રિએક્ટ ફાઈબરનો જાદુ તેના ટુ-ફેઝ કમિટ આર્કિટેક્ચર દ્વારા સાકાર થાય છે. આ વિભાજન જ રેન્ડરિંગને દ્રશ્ય અસંગતતાઓ વિના વિક્ષેપિત કરી શકાય તેવું બનાવે છે.
ફેઝ 1: રેન્ડર/રિકન્સિલિએશન ફેઝ (એસિન્ક્રોનસ અને ઇન્ટરપ્ટિબલ)
આ તે જગ્યા છે જ્યાં રિએક્ટ ભારે કામ કરે છે. કમ્પોનન્ટ ટ્રીના રુટથી શરૂ કરીને, રિએક્ટ `workLoop` માં ફાઈબર નોડ્સને ટ્રાવર્સ કરે છે. દરેક ફાઈબર માટે, તે નક્કી કરે છે કે તેને અપડેટ કરવાની જરૂર છે કે કેમ. તે તમારા કમ્પોનન્ટ્સને કૉલ કરે છે, નવા એલિમેન્ટ્સને જૂના ફાઈબર્સ સાથે સરખાવે છે, અને સાઇડ ઇફેક્ટ્સની યાદી બનાવે છે (દા.ત., "આ DOM નોડ ઉમેરો", "આ એટ્રિબ્યુટ અપડેટ કરો", "આ કમ્પોનન્ટ દૂર કરો").
આ ફેઝની નિર્ણાયક વિશેષતા એ છે કે તે એસિન્ક્રોનસ છે અને તેને વિક્ષેપિત કરી શકાય છે. થોડા ફાઈબર્સ પર પ્રક્રિયા કર્યા પછી, રિએક્ટ તપાસે છે કે શું તેણે તેનો ફાળવેલ સમયનો ટુકડો (સામાન્ય રીતે થોડી મિલિસેકન્ડ્સ) `shouldYield` નામના આંતરિક ફંક્શન દ્વારા પૂરો કરી દીધો છે. જો કોઈ ઉચ્ચ-પ્રાથમિકતાવાળી ઘટના બની હોય (જેમ કે યુઝર ઇનપુટ) અથવા જો તેનો સમય પૂરો થઈ ગયો હોય, તો રિએક્ટ તેનું કામ રોકી દેશે, ફાઈબર ટ્રીમાં તેની પ્રગતિ સાચવશે, અને બ્રાઉઝરના મુખ્ય થ્રેડને નિયંત્રણ પાછું સોંપશે. એકવાર બ્રાઉઝર ફરીથી મુક્ત થાય, રિએક્ટ જ્યાંથી છોડ્યું હતું ત્યાંથી જ શરૂ કરી શકે છે.
આ સમગ્ર ફેઝ દરમિયાન, કોઈ પણ ફેરફાર DOM માં ફ્લશ કરવામાં આવતો નથી. યુઝર જૂનું, સુસંગત UI જુએ છે. આ નિર્ણાયક છે - જો રિએક્ટ ક્રમશઃ ફેરફારો લાગુ કરે, તો યુઝરને તૂટેલું, અડધું-રેન્ડર થયેલું ઇન્ટરફેસ દેખાશે. બધા મ્યુટેશન્સની ગણતરી કરવામાં આવે છે અને મેમરીમાં એકત્રિત કરવામાં આવે છે, કમિટ ફેઝની રાહ જોતા.
ફેઝ 2: કમિટ ફેઝ (સિન્ક્રોનસ અને અનઇન્ટરપ્ટિબલ)
એકવાર રેન્ડર ફેઝ સમગ્ર અપડેટેડ ટ્રી માટે વિક્ષેપ વિના પૂર્ણ થઈ જાય, રિએક્ટ કમિટ ફેઝમાં જાય છે. આ ફેઝમાં, તે એકત્રિત કરેલી સાઇડ ઇફેક્ટ્સની યાદી લે છે અને તેને DOM પર લાગુ કરે છે.
આ ફેઝ સિન્ક્રોનસ છે અને તેને વિક્ષેપિત કરી શકાતો નથી. DOM ને અણુરૂપે અપડેટ કરવામાં આવે તે સુનિશ્ચિત કરવા માટે તેને એક જ, ઝડપી ધડાકામાં ચલાવવાની જરૂર છે. આ યુઝરને ક્યારેય અસંગત અથવા આંશિક રીતે અપડેટ થયેલું UI જોવાથી અટકાવે છે. આ તે સમય પણ છે જ્યારે રિએક્ટ `componentDidMount` અને `componentDidUpdate` જેવી લાઇફસાઇકલ મેથડ્સ, તેમજ `useLayoutEffect` હૂક ચલાવે છે. કારણ કે તે સિન્ક્રોનસ છે, તમારે `useLayoutEffect` માં લાંબા સમય સુધી ચાલતા કોડને ટાળવો જોઈએ કારણ કે તે પેઇન્ટિંગને બ્લોક કરી શકે છે.
કમિટ ફેઝ પૂર્ણ થયા પછી અને DOM અપડેટ થયા પછી, રિએક્ટ `useEffect` હૂકને એસિન્ક્રોનસ રીતે ચલાવવા માટે શેડ્યૂલ કરે છે. આ સુનિશ્ચિત કરે છે કે `useEffect` ની અંદરનો કોઈપણ કોડ (જેમ કે ડેટા ફેચિંગ) બ્રાઉઝરને અપડેટેડ UI ને સ્ક્રીન પર પેઇન્ટ કરવાથી અવરોધે નહીં.
વ્યવહારુ અસરો અને API કંટ્રોલ
થિયરી સમજવી સરસ છે, પરંતુ ગ્લોબલ ટીમોમાં ડેવલપર્સ આ શક્તિશાળી સિસ્ટમનો લાભ કેવી રીતે લઈ શકે છે? રિએક્ટ 18 એ કેટલીક APIs રજૂ કરી છે જે ડેવલપર્સને રેન્ડરિંગ પ્રાથમિકતા પર સીધું નિયંત્રણ આપે છે.
ઓટોમેટિક બેચિંગ
રિએક્ટ 18 માં, બધા સ્ટેટ અપડેટ્સ આપમેળે બેચ થાય છે, ભલે તે ક્યાંથી ઉદ્ભવ્યા હોય. અગાઉ, ફક્ત રિએક્ટ ઇવેન્ટ હેન્ડલર્સની અંદરના અપડેટ્સ જ બેચ થતા હતા. પ્રોમિસ, `setTimeout`, અથવા નેટિવ ઇવેન્ટ હેન્ડલર્સની અંદરના અપડેટ્સ દરેક એક અલગ રી-રેન્ડર ટ્રિગર કરતા હતા. હવે, શેડ્યૂલરનો આભાર, રિએક્ટ એક "ટિક" ની રાહ જુએ છે અને તે ટિકની અંદર થતા તમામ સ્ટેટ અપડેટ્સને એક જ, ઑપ્ટિમાઇઝ્ડ રી-રેન્ડરમાં બેચ કરે છે. આ બિનજરૂરી રેન્ડર્સ ઘટાડે છે અને ડિફોલ્ટ રૂપે પ્રદર્શન સુધારે છે.
startTransition API
રેન્ડરિંગ પ્રાથમિકતાને નિયંત્રિત કરવા માટે આ કદાચ સૌથી મહત્વપૂર્ણ API છે. `startTransition` તમને કોઈ ચોક્કસ સ્ટેટ અપડેટને બિન-તાકીદનું અથવા "ટ્રાન્ઝિશન" તરીકે ચિહ્નિત કરવાની મંજૂરી આપે છે.
એક સર્ચ ઇનપુટ ફીલ્ડની કલ્પના કરો. જ્યારે યુઝર ટાઇપ કરે છે, ત્યારે બે વસ્તુઓ થવી જરૂરી છે: 1. નવો અક્ષર બતાવવા માટે ઇનપુટ ફીલ્ડ પોતે જ અપડેટ થવું જોઈએ (ઉચ્ચ પ્રાથમિકતા). 2. શોધ પરિણામોની યાદી ફિલ્ટર અને ફરીથી રેન્ડર થવી જોઈએ, જે ધીમી કામગીરી હોઈ શકે છે (ઓછી પ્રાથમિકતા).
`startTransition` વિના, બંને અપડેટ્સની પ્રાથમિકતા સમાન હશે, અને ધીમી રેન્ડર થતી યાદી ઇનપુટ ફીલ્ડને ધીમું કરી શકે છે, જે ખરાબ યુઝર એક્સપિરિયન્સ બનાવે છે. યાદીના અપડેટને `startTransition` માં રેપ કરીને, તમે રિએક્ટને કહો છો: "આ અપડેટ નિર્ણાયક નથી. તમે નવી યાદી તૈયાર કરો ત્યારે થોડીવાર માટે જૂની યાદી બતાવવાનું ઠીક છે. ઇનપુટ ફીલ્ડને રિસ્પોન્સિવ બનાવવાની પ્રાથમિકતા આપો."
અહીં એક વ્યવહારુ ઉદાહરણ છે:
શોધ પરિણામો લોડ થઈ રહ્યા છે...
import { useState, useTransition } from 'react';
function SearchPage() {
const [isPending, startTransition] = useTransition();
const [inputValue, setInputValue] = useState('');
const [searchQuery, setSearchQuery] = useState('');
const handleInputChange = (e) => {
// હાઈ-પ્રાયોરિટી અપડેટ: ઇનપુટ ફીલ્ડને તરત જ અપડેટ કરો
setInputValue(e.target.value);
// લો-પ્રાયોરિટી અપડેટ: ધીમા સ્ટેટ અપડેટને ટ્રાન્ઝિશનમાં રેપ કરો
startTransition(() => {
setSearchQuery(e.target.value);
});
};
return (
આ કોડમાં, `setInputValue` એક ઉચ્ચ-પ્રાથમિકતા અપડેટ છે, જે ખાતરી કરે છે કે ઇનપુટ ક્યારેય ધીમું ન પડે. `setSearchQuery`, જે સંભવિત ધીમા `SearchResults` કમ્પોનન્ટને ફરીથી રેન્ડર કરવા માટે ટ્રિગર કરે છે, તેને ટ્રાન્ઝિશન તરીકે ચિહ્નિત કરવામાં આવ્યું છે. જો યુઝર ફરીથી ટાઇપ કરે તો રિએક્ટ આ ટ્રાન્ઝિશનને વિક્ષેપિત કરી શકે છે, જૂના રેન્ડર કામને ફેંકી દે છે અને નવી ક્વેરી સાથે નવેસરથી શરૂઆત કરે છે. `useTransition` હૂક દ્વારા પૂરો પાડવામાં આવેલ `isPending` ફ્લેગ આ ટ્રાન્ઝિશન દરમિયાન યુઝરને લોડિંગ સ્ટેટ બતાવવાનો એક અનુકૂળ માર્ગ છે.
useDeferredValue હૂક
`useDeferredValue` સમાન પરિણામ પ્રાપ્ત કરવા માટે એક અલગ રીત પ્રદાન કરે છે. તે તમને ટ્રીના બિન-નિર્ણાયક ભાગના રી-રેન્ડરિંગને મુલતવી રાખવા દે છે. તે ડિબાઉન્સ લાગુ કરવા જેવું છે, પરંતુ ઘણું સ્માર્ટ કારણ કે તે સીધું રિએક્ટના શેડ્યૂલર સાથે સંકલિત છે.
તે એક વેલ્યુ લે છે અને તે વેલ્યુની નવી કૉપિ પરત કરે છે જે રેન્ડર દરમિયાન મૂળ કરતાં "પાછળ રહેશે". જો વર્તમાન રેન્ડર તાત્કાલિક અપડેટ (જેમ કે યુઝર ઇનપુટ) દ્વારા ટ્રિગર થયું હોય, તો રિએક્ટ પહેલા જૂની, ડિફર્ડ વેલ્યુ સાથે રેન્ડર કરશે અને પછી નીચલી પ્રાથમિકતા પર નવી વેલ્યુ સાથે રી-રેન્ડર શેડ્યૂલ કરશે.
ચાલો `useDeferredValue` નો ઉપયોગ કરીને શોધ ઉદાહરણને રિફેક્ટર કરીએ:
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
const handleInputChange = (e) => {
setQuery(e.target.value);
};
return (
અહીં, `input` હંમેશા નવીનતમ `query` સાથે અપ-ટુ-ડેટ હોય છે. જોકે, `SearchResults` ને `deferredQuery` મળે છે. જ્યારે યુઝર ઝડપથી ટાઇપ કરે છે, ત્યારે `query` દરેક કીસ્ટ્રોક પર અપડેટ થાય છે, પરંતુ `deferredQuery` તેની પાછલી વેલ્યુ ત્યાં સુધી પકડી રાખશે જ્યાં સુધી રિએક્ટ પાસે થોડો સમય ન હોય. આ યાદીના રેન્ડરિંગને અસરકારક રીતે ડી-પ્રાયોરિટાઇઝ કરે છે, UI ને ફ્લુઇડ રાખે છે.
પ્રાયોરિટી લેન્સની કલ્પના: એક મેન્ટલ મોડેલ
ચાલો આ મેન્ટલ મોડેલને મજબૂત કરવા માટે એક જટિલ દૃશ્યમાંથી પસાર થઈએ. એક સોશિયલ મીડિયા ફીડ એપ્લિકેશનની કલ્પના કરો:
- પ્રારંભિક સ્થિતિ: યુઝર પોસ્ટ્સની લાંબી યાદીમાંથી સ્ક્રોલ કરી રહ્યો છે. આ નવી આઇટમ્સ દૃશ્યમાં આવતાની સાથે રેન્ડર કરવા માટે `NormalPriority` અપડેટ્સને ટ્રિગર કરે છે.
- ઉચ્ચ-પ્રાથમિકતા વિક્ષેપ: સ્ક્રોલ કરતી વખતે, યુઝર પોસ્ટના કમેન્ટ બોક્સમાં ટિપ્પણી ટાઇપ કરવાનું નક્કી કરે છે. આ ટાઇપિંગ ક્રિયા ઇનપુટ ફીલ્ડમાં `ImmediatePriority` અપડેટ્સને ટ્રિગર કરે છે.
- સમવર્તી લો-પ્રાયોરિટી કાર્ય: કમેન્ટ બોક્સમાં એક ફીચર હોઈ શકે છે જે ફોર્મેટ કરેલા ટેક્સ્ટનું લાઇવ પ્રિવ્યૂ બતાવે છે. આ પ્રિવ્યૂ રેન્ડર કરવું ધીમું હોઈ શકે છે. આપણે પ્રિવ્યૂ માટેના સ્ટેટ અપડેટને `startTransition` માં રેપ કરી શકીએ છીએ, તેને `LowPriority` અપડેટ બનાવીને.
- બેકગ્રાઉન્ડ અપડેટ: તે જ સમયે, નવી પોસ્ટ્સ માટે બેકગ્રાઉન્ડ `fetch` કૉલ પૂર્ણ થાય છે, જે ફીડની ટોચ પર "New Posts Available" બેનર ઉમેરવા માટે બીજું `NormalPriority` સ્ટેટ અપડેટ ટ્રિગર કરે છે.
રિએક્ટનો શેડ્યૂલર આ ટ્રાફિકનું સંચાલન કેવી રીતે કરશે તે અહીં છે:
- રિએક્ટ તરત જ `NormalPriority` સ્ક્રોલ રેન્ડરિંગ કાર્યને રોકી દે છે.
- તે `ImmediatePriority` ઇનપુટ અપડેટ્સને તરત જ હેન્ડલ કરે છે. યુઝરનું ટાઇપિંગ સંપૂર્ણપણે રિસ્પોન્સિવ લાગે છે.
- તે બેકગ્રાઉન્ડમાં `LowPriority` કમેન્ટ પ્રિવ્યૂ રેન્ડર પર કામ શરૂ કરે છે.
- `fetch` કૉલ પરત આવે છે, બેનર માટે `NormalPriority` અપડેટ શેડ્યૂલ કરે છે. કારણ કે આ કમેન્ટ પ્રિવ્યૂ કરતાં વધુ પ્રાથમિકતા ધરાવે છે, રિએક્ટ પ્રિવ્યૂ રેન્ડરિંગને રોકશે, બેનર અપડેટ પર કામ કરશે, તેને DOM પર કમિટ કરશે, અને પછી જ્યારે તેની પાસે નિષ્ક્રિય સમય હશે ત્યારે પ્રિવ્યૂ રેન્ડરિંગ ફરી શરૂ કરશે.
- એકવાર બધી યુઝર ક્રિયાપ્રતિક્રિયાઓ અને ઉચ્ચ-પ્રાથમિકતાવાળા કાર્યો પૂર્ણ થઈ જાય, રિએક્ટ મૂળ `NormalPriority` સ્ક્રોલ રેન્ડરિંગ કાર્યને જ્યાંથી છોડ્યું હતું ત્યાંથી ફરી શરૂ કરે છે.
કામનું આ ગતિશીલ રોકવું, પ્રાથમિકતા આપવી અને ફરી શરૂ કરવું એ પ્રાયોરિટી લેન મેનેજમેન્ટનો સાર છે. તે સુનિશ્ચિત કરે છે કે યુઝરની પ્રદર્શનની ધારણા હંમેશા ઑપ્ટિમાઇઝ્ડ હોય છે કારણ કે સૌથી નિર્ણાયક ક્રિયાપ્રતિક્રિયાઓ ક્યારેય ઓછી નિર્ણાયક બેકગ્રાઉન્ડ કાર્યો દ્વારા અવરોધિત થતી નથી.
વૈશ્વિક પ્રભાવ: ફક્ત સ્પીડથી વિશેષ
રિએક્ટના કન્કરન્ટ રેન્ડરિંગ મોડેલના ફાયદા ફક્ત એપ્લિકેશન્સને ઝડપી અનુભવ કરાવવા પૂરતા સીમિત નથી. તેઓ વૈશ્વિક યુઝર બેઝ માટે મુખ્ય વ્યવસાય અને ઉત્પાદન મેટ્રિક્સ પર મૂર્ત અસર કરે છે.
- ઍક્સેસિબિલિટી: એક રિસ્પોન્સિવ UI એ એક ઍક્સેસિબલ UI છે. જ્યારે ઇન્ટરફેસ ફ્રીઝ થાય છે, ત્યારે તે બધા યુઝર્સ માટે દિશાહિન અને બિનઉપયોગી હોઈ શકે છે, પરંતુ તે ખાસ કરીને સ્ક્રીન રીડર્સ જેવી સહાયક તકનીકો પર આધાર રાખનારાઓ માટે સમસ્યારૂપ છે, જે સંદર્ભ ગુમાવી શકે છે અથવા બિનપ્રતિભાવશીલ બની શકે છે.
- યુઝર રિટેન્શન: સ્પર્ધાત્મક ડિજિટલ લેન્ડસ્કેપમાં, પ્રદર્શન એક ફીચર છે. ધીમી, જંકી એપ્લિકેશન્સ યુઝરની નિરાશા, ઊંચા બાઉન્સ રેટ અને ઓછી સંલગ્નતા તરફ દોરી જાય છે. એક ફ્લુઇડ અનુભવ આધુનિક સોફ્ટવેરની મુખ્ય અપેક્ષા છે.
- ડેવલપર એક્સપિરિયન્સ: લાઇબ્રેરીમાં જ આ શક્તિશાળી શેડ્યૂલિંગ પ્રિમિટિવ્સ બનાવીને, રિએક્ટ ડેવલપર્સને જટિલ, પર્ફોર્મન્ટ UI ને વધુ ઘોષણાત્મક રીતે બનાવવાની મંજૂરી આપે છે. જટિલ ડિબાઉન્સિંગ, થ્રોટલિંગ, અથવા `requestIdleCallback` લોજિકને મેન્યુઅલી લાગુ કરવાને બદલે, ડેવલપર્સ `startTransition` જેવી APIs નો ઉપયોગ કરીને રિએક્ટને ફક્ત તેમના ઇરાદાનો સંકેત આપી શકે છે, જે સ્વચ્છ, વધુ જાળવણી યોગ્ય કોડ તરફ દોરી જાય છે.
ગ્લોબલ ડેવલપમેન્ટ ટીમો માટે કાર્યક્ષમ પગલાં
- કન્કરન્સીને અપનાવો: ખાતરી કરો કે તમારી ટીમ રિએક્ટ 18 નો ઉપયોગ કરી રહી છે અને નવા કન્કરન્ટ ફીચર્સને સમજે છે. આ એક પેરાડાઈમ શિફ્ટ છે.
- ટ્રાન્ઝિશન્સ ઓળખો: તમારી એપ્લિકેશનમાં કોઈપણ UI અપડેટ્સ માટે ઓડિટ કરો જે તાત્કાલિક નથી. સંબંધિત સ્ટેટ અપડેટ્સને `startTransition` માં રેપ કરો જેથી તેઓ વધુ નિર્ણાયક ક્રિયાપ્રતિક્રિયાઓને અવરોધે નહીં.
- ભારે રેન્ડર્સને મુલતવી રાખો: જે કમ્પોનન્ટ્સ રેન્ડર કરવામાં ધીમા હોય અને ઝડપથી બદલાતા ડેટા પર આધાર રાખતા હોય, તેમના રી-રેન્ડરિંગને ડી-પ્રાયોરિટાઇઝ કરવા અને બાકીની એપ્લિકેશનને સ્નેપી રાખવા માટે `useDeferredValue` નો ઉપયોગ કરો.
- પ્રોફાઇલ અને માપન કરો: તમારા કમ્પોનન્ટ્સ કેવી રીતે રેન્ડર થાય છે તે વિઝ્યુઅલાઈઝ કરવા માટે રિએક્ટ ડેવટૂલ્સ પ્રોફાઇલરનો ઉપયોગ કરો. પ્રોફાઇલર કન્કરન્ટ રિએક્ટ માટે અપડેટ થયેલ છે અને તમને ઓળખવામાં મદદ કરી શકે છે કે કયા અપડેટ્સ વિક્ષેપિત થઈ રહ્યા છે અને કયા પ્રદર્શનમાં અવરોધો પેદા કરી રહ્યા છે.
- શિક્ષિત કરો અને પ્રચાર કરો: તમારી ટીમમાં આ વિભાવનાઓને પ્રોત્સાહન આપો. પર્ફોર્મન્ટ એપ્લિકેશન્સ બનાવવી એ એક સામૂહિક જવાબદારી છે, અને શ્રેષ્ઠ કોડ લખવા માટે રિએક્ટના શેડ્યૂલરની સહિયારી સમજ નિર્ણાયક છે.
નિષ્કર્ષ
રિએક્ટ ફાઈબર અને તેનું પ્રાયોરિટી-આધારિત શેડ્યૂલર ફ્રન્ટ-એન્ડ ફ્રેમવર્ક્સના ઉત્ક્રાંતિમાં એક ભવ્ય છલાંગનું પ્રતિનિધિત્વ કરે છે. અમે બ્લોકિંગ, સિન્ક્રોનસ રેન્ડરિંગની દુનિયામાંથી સહકારી, વિક્ષેપિત કરી શકાય તેવા શેડ્યૂલિંગના નવા પેરાડાઈમમાં આગળ વધ્યા છીએ. કામને વ્યવસ્થિત ફાઈબર ટુકડાઓમાં વિભાજીત કરીને અને તે કામને પ્રાથમિકતા આપવા માટે એક અત્યાધુનિક લેન મોડેલનો ઉપયોગ કરીને, રિએક્ટ ખાતરી કરી શકે છે કે યુઝર-ફેસિંગ ક્રિયાપ્રતિક્રિયાઓ હંમેશા પહેલા હેન્ડલ કરવામાં આવે, એવી એપ્લિકેશન્સ બનાવે જે ફ્લુઇડ અને ત્વરિત લાગે, ભલે બેકગ્રાઉન્ડમાં જટિલ કાર્યો કરતી હોય.
ડેવલપર્સ માટે, ટ્રાન્ઝિશન્સ અને ડિફર્ડ વેલ્યુઝ જેવી વિભાવનાઓમાં નિપુણતા મેળવવી એ હવે વૈકલ્પિક ઑપ્ટિમાઇઝેશન નથી - તે આધુનિક, ઉચ્ચ-પ્રદર્શન વેબ એપ્લિકેશન્સ બનાવવા માટે એક મુખ્ય યોગ્યતા છે. રિએક્ટના પ્રાયોરિટી લેન મેનેજમેન્ટને સમજીને અને તેનો લાભ લઈને, તમે વૈશ્વિક પ્રેક્ષકોને શ્રેષ્ઠ યુઝર એક્સપિરિયન્સ પ્રદાન કરી શકો છો, એવા ઇન્ટરફેસ બનાવી શકો છો જે ફક્ત કાર્યાત્મક જ નહીં, પરંતુ વાપરવામાં ખરેખર આનંદદાયક હોય.